<?php

namespace hs\rabbitmq;
use think\Config;
use think\facade\Cache;
use think\facade\Log;

trait Service{



    //队列执行状态
    public $queue_exec_status = true;

    //对列执行信息
    public $queue_exec_msg;

    //队列执行开始时间
    public $queue_exec_starttime = '';

    public $queue_exec_delay = 0.001;


    public $taksModel = null;

    //队列信息
    public $queue_msg = [];

    public function getTask() :static
    {
        $solevar = $this->queue_msg['solevar'];
        $this->taksModel = Task::model()->where("solevar",$solevar)->order('id desc')->findOrEmpty();
        return $this;
    }


    public function isExecMax() :bool
    {
        return $this->taksModel->number <= $this->taksModel->exec_number;
    }


    //重置任务
    public function release(Task $model)
    {
        $delay = \think\facade\Config::get("rabbitmq.queue.delay",[1]);
        return $model->save([
            "status"         => 1,
            "number"         => count($delay) ,
            "exec_number"    => 0 ,
            "next_exec_time" => date('Y-m-d H:i:s'),
        ]);
    }


    public function setNextExecTime(){
        $delay = \think\facade\Config::get("rabbitmq.queue.{$this->taksModel->queue_name}")["delay"] ?? [];
        $next  = $this->taksModel->exec_number + 1;
        if(count($delay) > 0){
            $this->queue_exec_delay = $delay[$next] ?? end($delay); /* 最后一个 */
        }
        $this->queue_exec_delay = $this->getExecDelayTime();
        return $this;
    }

    //重新入队
    public function retry():static
    {
        RabbitFacade::pushlazy($this->queue_msg,$this->queue_msg['queue_name']);
        return $this;
    }

    public function setQueueMsg($data):static
    {
        $this->queue_msg = $data;
        return $this;
    }

    public function insertTask(array $param): string
    {
        $next    = time() + $this->getExecDelayTime();
        $solevar = $this->createTaskId();
        $this->taksModel = Task::model()->create([
            "solevar"        => $solevar,
            "number"         => $param['retry_number'],
            "body"           => json_encode($param['attach']),
            "queue_name"     => $param['queue_name'],
            "exec_class"     => $param['class_name'],
            "exec_func"      => $param['func'],
            "next_exec_time" => date('Y-m-d H:i:s',$next),
        ]);
        if(intval($this->taksModel->id) > 0){
            return $solevar;
        }
        return '';
    }


    public function setExecStartTime(): static
    {
        $this->queue_exec_starttime = date('Y-m-d H:i:s');
        return $this;
    }

    public function setExecMsg(string $solevar,string $msg) :static
    {
        Cache::set("exec_msg:{$solevar}",$msg);
        return $this;
    }


    public function getExecDelayTime()
    {
        return $this->queue_exec_delay * 1000;
    }



    public function insertTaskExec(): void
    {
        $task = $this->taksModel;
        $cacheKey = "exec_msg:{$task->solevar}";
        $qem  = Cache::get($cacheKey);
        $task->startTrans();
        $task->exec_number += 1;
        $task->save();
        $exec = TaskExec::model()->create([
            "solevar"          => $task->solevar,
            "status"           => $task->status == 2 ? 1 : 2,
            "response"         => $qem,
            "exec_start_time"  => $this->queue_exec_starttime,
            "exec_end_time"    => date('Y-m-d H:i:s'),
            "exec_number"      => $task->exec_number,
        ]);
        if(intval($exec->id)){
            $task->commit();
        }else{
            $task->rollback();
        }
        Cache::delete($cacheKey);
    }


    public function createTaskId() :string
    {
        $houseNum     = time()-strtotime(date('Y-m-d'));
        $time         = date('ymd');
        $length       = 20;
        $prefixTime   = $time.$houseNum;
        $lastLen      = $length - strlen($prefixTime);
        $utimestamp   = microtime(true);
        $timestamp    = floor($utimestamp);
        $milliseconds = round(($utimestamp - $timestamp) * 1000000);
        $orderNo      = $prefixTime.$milliseconds;
        if($lastLen-strlen($milliseconds)>0){
            for($i=0;$i<($lastLen-strlen($milliseconds));$i++){
                $orderNo .= rand(1,9);
            }
        }
        return "QT-" . $orderNo;
    }
    
}